package thread

import (
	"fmt"
	"strings"
	"time"

	"gitee.com/sansaniot/ssiot-core/facade/env"
	"gitee.com/sansaniot/ssiot-core/logger"

	"ssdevice/common/constant"
	"ssdevice/common/enums"
)

type DevStatusUpdateThread struct {
}

type devUpdate struct {
	Sn           string
	LastLiveTime string
}

func (DevStatusUpdateThread) Run(threadName string) {
	logger.Infof("启动线程 - %s.", threadName)

	go func() {
		dataList := make([]devUpdate, 0)
		for {
			// 缓存慢更新, 查询查的缓存
			time.Sleep(time.Duration(constant.CacheFlushSecInterval) * time.Second)
			// 遍历
			constant.DevOnlineCache.IterCb(func(sn string, lastLiveTime string) {
				// 仅更新末次交互改变的
				if !constant.StatusSnCache.Has(sn) {
					return
				}
				// 末次时间缓存
				du := devUpdate{
					Sn:           sn,
					LastLiveTime: lastLiveTime,
				}
				dataList = append(dataList, du)
				// 下次不用更新了
				constant.StatusSnCache.Remove(sn)
				// 批量更新
				if len(dataList) > constant.ThreadBatchSize {
					// 批量处理数据
					dealDevStatus(dataList)
					// 清空(减少扩容)
					dataList = dataList[0:0]
				}
			})
			if len(dataList) > 0 {
				// 批量处理数据
				dealDevStatus(dataList)
				// 清空(减少扩容)
				dataList = dataList[0:0]
			}
		}
	}()
}

func dealDevStatus(dataList []devUpdate) {
	t1 := time.Now()
	sql := "UPDATE sys_dev SET online_status = tmp.status, last_live_time = to_timestamp(tmp.liveTime,'yyyy-MM-DD hh24:mi:ss') FROM (VALUES %s) as tmp (sn, status, liveTime) where sys_dev.sn = tmp.sn "
	valueSql := make([]string, 0)
	for _, s := range dataList {
		valueSql = append(valueSql, "('"+s.Sn+"','"+enums.Online+"','"+s.LastLiveTime+"')")
	}
	sql = fmt.Sprintf(sql, strings.Join(valueSql, ","))
	if err := env.Db.Raw(sql).Scan(&scan).Error; err != nil {
		logger.Error(err)
	}
	logger.Infof("设备状态批量更新%d. 耗时%v", len(dataList), time.Since(t1).Round(time.Millisecond))
}
